package com.example.baidu_map_plugin.mapview;


import android.content.Context;

import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;

import androidx.annotation.NonNull;


import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.BitmapDescriptor;
import com.baidu.mapapi.map.BitmapDescriptorFactory;
import com.baidu.mapapi.map.MapStatus;
import com.baidu.mapapi.map.MapStatusUpdate;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.CoordType;
import com.baidu.mapapi.SDKInitializer;

import com.baidu.mapapi.map.Marker;
import com.baidu.mapapi.map.MarkerOptions;
import com.baidu.mapapi.map.OverlayOptions;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.utils.CoordinateConverter;
import com.example.baidu_map_plugin.R;
import com.example.baidu_map_plugin.data.MethodType;
import com.google.gson.Gson;

import java.util.ArrayList;
import java.util.List;

import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.platform.PlatformView;

import static com.baidu.mapapi.BMapManager.getContext;
import static io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import static io.flutter.plugin.common.MethodChannel.Result;

public class FlutterNativeBaiDuMapView implements PlatformView, MethodCallHandler {
    private static final String TAG = FlutterNativeBaiDuMapView.class.getSimpleName();
    private final MethodChannel methodChannel;
    private MapView mapView;
    private BaiduMap baiduMap;
    private FlutterNativeBaiDuViewModel flutterNativeBaiduViewModel;
    private MapStatus mMapStatus;
    private BitmapDescriptor clearSelectedBitmapDescriptor;
    private BitmapDescriptor clearUnSelectedBitmapDescriptor;
    private final List<FlutterNativeBaiDuViewModel.OverlayOption> selectedOverlayOptions;

    public FlutterNativeBaiDuMapView(Context context, BinaryMessenger messenger, int id, Object initial) {
        selectedOverlayOptions = new ArrayList<>();
        methodChannel = new MethodChannel(messenger, "plugins.baidumapplugin_example/mapview_" + id);
        methodChannel.setMethodCallHandler(this);
        flutterNativeBaiduViewModel = new Gson().fromJson((String) initial, FlutterNativeBaiDuViewModel.class);
        initMap(context);
    }

    private void initMap(Context context) {
        SDKInitializer.initialize(context.getApplicationContext());
        SDKInitializer.setCoordType(CoordType.BD09LL);
        this.mapView = (MapView) LayoutInflater.from(context).inflate(R.layout.map_view, null);
        baiduMap = mapView.getMap();
        clearSelectedBitmapDescriptor = BitmapDescriptorFactory.fromResource(R.mipmap.map_clear_selected);
        clearUnSelectedBitmapDescriptor = BitmapDescriptorFactory.fromResource(R.mipmap.map_clear_un_selected);
        drawPoiOnMap();
        baiduMap.setOnMarkerClickListener(new BaiduMap.OnMarkerClickListener() {
            @Override
            public boolean onMarkerClick(Marker marker) {
                if (marker != null && marker.getExtraInfo() != null) {
                    FlutterNativeBaiDuViewModel.OverlayOption overlayOption = (FlutterNativeBaiDuViewModel.OverlayOption) marker.getExtraInfo().getSerializable("overlayOption");
                    Log.e(TAG, "onMarkerClick():overlayOption=" + overlayOption);
                    if (overlayOption != null) {
                        if (!selectedOverlayOptions.contains(overlayOption)) {
                            selectedOverlayOptions.add(overlayOption);
                        } else {
                            selectedOverlayOptions.remove(overlayOption);
                        }
                        overlayOption.isSelect = !overlayOption.isSelect;
                        methodChannel.invokeMethod("onSelectedOverlay", new Gson().toJson(overlayOption));
                        mMapStatus = baiduMap.getMapStatus();
                        drawPoiOnMap();
                    }
                }
                return false;
            }
        });
    }

    private void drawPoiOnMap() {
        baiduMap.clear();
        if (flutterNativeBaiduViewModel != null) {
            switch (flutterNativeBaiduViewModel.type) {
                case 0:
                    drawClear();
                    break;
                default:
            }

        }
    }

    private void drawClear() {
        if (flutterNativeBaiduViewModel.overlayOptions != null) {
            List<OverlayOptions> overlayOptions1 = getOverlayOptions(flutterNativeBaiduViewModel.overlayOptions);
            if (mMapStatus == null) {
                mMapStatus = new MapStatus.Builder()
                        // .target(new LatLng(flutterNativeBaiduViewModel.overlayOptions.get(0).latitude, flutterNativeBaiduViewModel.overlayOptions.get(0).longitude))
                        .zoom(18)
                        .build();
            }
            MapStatusUpdate mMapStatusUpdate = MapStatusUpdateFactory.newMapStatus(mMapStatus);
            baiduMap.setMapStatus(mMapStatusUpdate);
            baiduMap.addOverlays(overlayOptions1);
        }
    }

    private List<OverlayOptions> getOverlayOptions(List<FlutterNativeBaiDuViewModel.OverlayOption> overlayOptions) {
        //设置marker
        List<OverlayOptions> overlayOptionsList = new ArrayList<>();
        BitmapDescriptor bitmapDescriptor = null;
        for (FlutterNativeBaiDuViewModel.OverlayOption overlayOption : overlayOptions) {
            if (overlayOption.isSelect) {
                bitmapDescriptor = clearSelectedBitmapDescriptor;
            } else {
                bitmapDescriptor = clearUnSelectedBitmapDescriptor;
            }
            OverlayOptions markerOptions = getMarkerOverlayOptions(bitmapDescriptor, overlayOption);
            overlayOptionsList.add(markerOptions);
            OverlayOptions textOverlayOptions = getTextOverlayOptions(overlayOption);
            if (textOverlayOptions != null) {
                overlayOptionsList.add(textOverlayOptions);
            }
        }
        return overlayOptionsList;
    }

    private OverlayOptions getMarkerOverlayOptions(BitmapDescriptor bitmapDescriptor, FlutterNativeBaiDuViewModel.OverlayOption overlayOption) {
        Bundle bundle = new Bundle();
        bundle.putSerializable("overlayOption", overlayOption);
        //初始化坐标转换工具类，指定源坐标类型和坐标数据
        LatLng desLatLng = getLatLng(overlayOption);
        return new MarkerOptions()
                .extraInfo(bundle)
                .position(desLatLng)//设置位置
                .icon(bitmapDescriptor)//设置图标样式
                .zIndex(9) // 设置marker所在层级
                .draggable(false)
                .yOffset(0)
                .perspective(true);
    }

    private LatLng getLatLng(FlutterNativeBaiDuViewModel.OverlayOption overlayOption) {
        // sourceLatLng待转换坐标
        CoordinateConverter converter  = new CoordinateConverter()
                .from(CoordinateConverter.CoordType.GPS)
                .coord(new LatLng(overlayOption.latitude, overlayOption.longitude));

        //desLatLng 转换后的坐标
        return converter.convert();
    }

    private OverlayOptions getTextOverlayOptions(FlutterNativeBaiDuViewModel.OverlayOption overlayOption) {
        //自定义布局
        TextView textView = new TextView(getContext());
        textView.setText(overlayOption.text);
        textView.setGravity(Gravity.CENTER);
        textView.setTextColor(Color.BLACK);
        LatLng desLatLng = getLatLng(overlayOption);
        //构建Marker图标
        BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory.fromView(textView);
        //构建MarkerOption，用于在地图上添加Marker
        if (bitmapDescriptor != null) {
            Bundle bundle = new Bundle();
            bundle.putSerializable("overlayOption", overlayOption);
            return new MarkerOptions()
                    .extraInfo(bundle)
                    .position(desLatLng)
                    .icon(bitmapDescriptor)
                    .yOffset(30);
        }
        return null;
    }

    @Override
    public View getView() {
        return mapView;
    }

    @Override
    public void onFlutterViewAttached(@NonNull View flutterView) {

    }

    @Override
    public void onMethodCall(MethodCall methodCall, Result result) {
        MethodType methodType = MethodType.getMethodType(methodCall.method);
        switch (methodType) {
            case updateMapView:
                updateMapView(methodCall, result);
                break;
            case setMapViewCenter:
                setMapViewCenter(methodCall, result);
                break;
            default:
                result.notImplemented();
        }

    }

    private void setMapViewCenter(MethodCall methodCall, Result result) {
        //SDKInitializer.setCoordType(CoordType.GCJ02);

        FlutterNativeBaiDuViewModel.OverlayOption overlayOption = new Gson().fromJson(new Gson().toJson(methodCall.arguments), FlutterNativeBaiDuViewModel.OverlayOption.class);
        Log.d(TAG, "setMapViewCenter():overlayOption=" + overlayOption);
        if (mMapStatus == null && overlayOption != null) {
            LatLng desLatLng = getLatLng(overlayOption);
            mMapStatus = new MapStatus.Builder()
                    .target(desLatLng)
                    .zoom(18)
                    .build();
            MapStatusUpdate mMapStatusUpdate = MapStatusUpdateFactory.newMapStatus(mMapStatus);
            baiduMap.setMapStatus(mMapStatusUpdate);
        }
        result.success(null);
    }

    private void updateMapView(MethodCall methodCall, Result result) {

        flutterNativeBaiduViewModel = new Gson().fromJson((String) methodCall.arguments, FlutterNativeBaiDuViewModel.class);
        Log.d(TAG, "updateMapView():flutterNativeBaiduViewModel=" + flutterNativeBaiduViewModel);
        drawPoiOnMap();
        result.success(null);
    }

    @Override
    public void dispose() {
        if (baiduMap != null) {
            baiduMap.clear();
        }
    }
}
